package presentation.control;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;

import javax.swing.JOptionPane;
import javax.swing.JTable;

import presentation.data.BrowseSelectData;
import presentation.data.DataUtil;
import presentation.data.MessagesUtil;
import presentation.gui.CartItemsWindow;
import presentation.gui.CatalogListWindow;
import presentation.gui.EbazaarMainFrame;
import presentation.gui.MaintainCatalogTypes;
import presentation.gui.MaintainProductCatalog;
import presentation.gui.ProductDetailsWindow;
import presentation.gui.ProductListWindow;
import presentation.gui.QuantityWindow;
import presentation.gui.SelectOrderWindow;
import business.SessionCache;
import business.exceptions.BackendException;
import business.exceptions.UIException;
import business.exceptions.UnauthorizedException;
import business.externalinterfaces.CustomerConstants;
import business.externalinterfaces.ShoppingCartSubsystem;


//
/*import business.util.ProductUtil;
 import business.util.ShoppingCartUtil;
 import business.util.StringParse;*/

public class BrowseSelectUIControl {
	// public methods (non-accessors)
	public void makeMainFrameVisible() {
		if (mainFrame == null) {
			mainFrame = new EbazaarMainFrame();
		}
		mainFrame.setVisible(true);
	}

	class PurchaseOnlineActionListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {

			catalogListWindow = new CatalogListWindow();

			// get presesntation data
			BrowseSelectData data = BrowseSelectData.getInstance();

			try {
				// data class asks for data
				List<String[]> catNames = data.getCatalogNames();
				catalogListWindow.updateModel(catNames);
				mainFrame.getDesktop().add(catalogListWindow);
				catalogListWindow.setVisible(true);
			} catch (BackendException ex) {
				MessagesUtil.displayErrorMsg(catalogListWindow, ex.getMessage());
			}
		}
	}

	class LoginListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {

			SessionCache ctx = SessionCache.getInstance();
			Boolean loggedIn = (Boolean) ctx.get(CustomerConstants.LOGGED_IN);
			if (!loggedIn.booleanValue()) {
				LoginUIControl loginControl = new LoginUIControl(mainFrame,
						mainFrame);

				loginControl.startLogin();
			} else {
				JOptionPane.showMessageDialog(null,
						"You are already logged in.", "Success",
						JOptionPane.INFORMATION_MESSAGE);
			}
		}

	}

	public ActionListener getNewOnlinePurchaseListener(EbazaarMainFrame f) {
		return (new PurchaseOnlineActionListener());
	}

	// ///// make this class a singleton
	private static final BrowseSelectUIControl instance = new BrowseSelectUIControl();

	public static BrowseSelectUIControl getInstance() {
		return instance;
	}

	private BrowseSelectUIControl() {
	}

	

	// control of CatalogListWindow
	class SelectCatalogListener implements ActionListener {
		BrowseSelectData data = BrowseSelectData.getInstance();

		public void actionPerformed(ActionEvent evt) {
			JTable table = catalogListWindow.getTable();
			try {
				//need to read data 
				productListWindow = new ProductListWindow(
						data.getCurrentSelectedCatalog(table));
				catalogListWindow.setVisible(false);
				mainFrame.getDesktop().add(productListWindow);
				productListWindow.setVisible(true);
			} catch (UIException e) {
				MessagesUtil.displayErrorMsg(catalogListWindow,
						e.getMessage());
			} 
		}
	}

	class BackToMainFrameListener implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent e) {
			mainFrame.setVisible(true);
			catalogListWindow.setVisible(false);

		}

	}

	class SelectProductListener implements ActionListener {
		BrowseSelectData data = BrowseSelectData.getInstance();
		boolean useDefaultData;

		public SelectProductListener(boolean useDefData) {

			useDefaultData = useDefData;
		}

		/* Returns, as a String array, the product details based on the type */

		@Override
		public void actionPerformed(ActionEvent e) {
			JTable table = productListWindow.getTable();
			try {
				String[] productParams = data.readProductDetailsData(table,
						useDefaultData);
				productDetailsWindow = new ProductDetailsWindow(productParams);
				mainFrame.getDesktop().add(productDetailsWindow);
				productListWindow.setVisible(false);
				productDetailsWindow.setVisible(true);
			} catch (UIException ex) {
				String errMsg = MessagesUtil.SELECT_ROW_MSG;
				MessagesUtil.displayErrorMsg(productListWindow, errMsg);
			} catch (BackendException ex) {
				MessagesUtil.displayErrorMsg(catalogListWindow, ex.getMessage());

			}
		}

	}

	class BackToCatalogListListener implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent e) {
			catalogListWindow.setVisible(true);
			productListWindow.setVisible(false);
		}

	}

	// ///// control ProductDetails

	class AddEditCartItemListener implements ActionListener {
		private boolean editMode = false;

		AddEditCartItemListener(boolean edit) {
			this.editMode = edit;
		}

		@Override
		public void actionPerformed(ActionEvent e) {

			BrowseSelectData data = BrowseSelectData.getInstance();
			if (editMode) {

				JTable table = cartItemsWindow.getTable();

				try {
					int selectedRow = data.readSelectedProductForEdit(table);
					
					//implement

				} catch (UIException ex) {
					MessagesUtil.displayErrorMsg(productListWindow, ex.getMessage());
				} catch (BackendException ex) {
					MessagesUtil.displayErrorMsg(catalogListWindow, ex.getMessage());
				}
			} else {
				productDetailsWindow.setVisible(false);
				quantityWindow = new QuantityWindow(false, null);
				EbazaarMainFrame.getInstance().getDesktop().add(quantityWindow);
				quantityWindow.setVisible(true);
			}
			quantityWindow.setParentWindow(productDetailsWindow);
		}
	}

	

	class DeleteCartItemListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			//implement
		}

	}

	class BackToProductListListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {

			productDetailsWindow.setVisible(false);
			productListWindow.setVisible(true);
		}

	}

	class ContinueShoppingListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			BrowseSelectData data = BrowseSelectData.getInstance();
			cartItemsWindow.setVisible(false);

			// user has been looking at this product list
			if (productListWindow != null) {
				productListWindow.setVisible(true);
			}
			// user has just retrieved saved cart
			else {

				if (catalogListWindow != null) {
					catalogListWindow.dispose();
				}
				catalogListWindow = new CatalogListWindow();

				// ProductSubsystemFacade prodSS = new ProductSubsystemFacade();

				List<String[]> newlist = null;
				try {

					newlist = data.getCatalogNames();

					catalogListWindow.updateModel(newlist);
				} catch (BackendException ex) {
					String errMsg = "Database is unavailable.";
					MessagesUtil.displayErrorMsg(catalogListWindow, errMsg);
				}
				EbazaarMainFrame.getInstance().getDesktop()
						.add(catalogListWindow);
				catalogListWindow.setVisible(true);
			}
		}
	}

	class SaveCartListener implements ActionListener, Callback {
		
		BrowseSelectData data = BrowseSelectData.getInstance();
		public void doUpdate() {
			//handle authorization
			try {
	    		Authorization.checkAuthorization(cartItemsWindow, DataUtil.custIsAdmin());
	    	} catch(UnauthorizedException e) {   
	        	MessagesUtil.displayErrorMsg(cartItemsWindow, 
	        			e.getMessage());
	        	return;
	        }
			
			//implement
			
			String msg = "Cart saved successfully.";
			JOptionPane.showMessageDialog(catalogListWindow, msg,
					"Success", JOptionPane.OK_OPTION);
			cartItemsWindow.setVisible(true);
			
		}

		public void actionPerformed(ActionEvent evt) {
			boolean isLoggedIn = data.isLoggedIn();
			if (!isLoggedIn) {
				cartItemsWindow.setVisible(false);
				LoginUIControl loginControl = new LoginUIControl(
						cartItemsWindow, cartItemsWindow, this);

				loginControl.startLogin();
			} else {
				doUpdate();
			}

		}

	}

	class QuantityOkListener implements ActionListener {

		private boolean editMode = false;
		private Integer positionOfEdit = null;

		QuantityOkListener(boolean edit, Integer posOfEdit) {
			this.editMode = edit;
			positionOfEdit = posOfEdit;
		}

		@Override
		public void actionPerformed(ActionEvent e) {
			BrowseSelectData data = BrowseSelectData.getInstance();
			String name = "name";
			String price = "0.0";
			// gather name and price in different ways for add and edit
			if (editMode) { // find name and price from corresponding position
							// in list of cartItems
				
			} else { // find name and price from the previous
						// productDetailsWindow
						// name = productDetailsWindow.getItem();
				
			}
			//try {

				String quantityReq = quantityWindow.getQuantityDesired();
				//run rules on quantity

				//when user edits quantity, we delete the cart item here, then add
				//it back as if it were a new cart item, with the new quantity
				if (editMode) { 
					//delete cart item by position
					cartItemsWindow.setVisible(false);
				}
				//add new cart item

				quantityWindow.dispose();
				productDetailsWindow.setVisible(false);
				cartItemsWindow = new CartItemsWindow();

				EbazaarMainFrame.getInstance().getDesktop()
						.add(cartItemsWindow);
				cartItemsWindow.setVisible(true);
			/*}

			catch (RuleException ex) {
				MessagesUtil.displayErrorMsg(catalogListWindow, ex.getMessage());
			} catch (DatabaseException ex) {
				String errMsg = "Database is unavailable.";
				MessagesUtil.displayErrorMsg(catalogListWindow, errMsg);

			} catch (BusinessException ex) {
				MessagesUtil.displayErrorMsg(catalogListWindow, MessagesUtil.GENERAL_ERR_MSG);
			} */
		}
	}
	
	class RetrieveCartActionListener implements ActionListener, Callback {
		BrowseSelectData data = BrowseSelectData.getInstance();
				
		public void doUpdate() {
			try {
	    		Authorization.checkAuthorization(cartItemsWindow, DataUtil.custIsAdmin());
	    	} catch(UnauthorizedException e) {   
	        	MessagesUtil.displayErrorMsg(cartItemsWindow, 
	        			e.getMessage());
	        	return;
	        }			
			ShoppingCartSubsystem shopCartSS = data.getShoppingCartSystem();
			
			// Saved cart was retrieved during login
			// Make saved cart live and then display the live cart in the usual way
			//shopCartSS.makeSavedCartLive();			
			//List<String[]> displayableListOfItems = data.getDisplayableCartItems();
			//cartItemsWindow.updateModel(displayableListOfItems);			
			
			//set total price
			//String totalPrice = String.valueOf(data.getLiveCartTotalCost());
			//cartItemsWindow.setTotal(totalPrice);
			
			EbazaarMainFrame.getInstance().getDesktop().add(cartItemsWindow);
			cartItemsWindow.setVisible(true);
		}

		public void actionPerformed(ActionEvent e) {
			cartItemsWindow = new CartItemsWindow();
			boolean isLoggedIn = data.isLoggedIn();
			if (!isLoggedIn) {
				LoginUIControl loginControl = new LoginUIControl(cartItemsWindow,
						mainFrame, this);
				loginControl.startLogin();
			} else {
				doUpdate();
			}
		}
	}
	

	// //////public getters available to GUI classes to set listeners in
	// components

	public LoginListener getLoginListener(EbazaarMainFrame f) {
		return new LoginListener();
	}
	public ActionListener getSelectCatalogListener(CatalogListWindow w) {
		return new SelectCatalogListener();
	}
	public ActionListener getBackToMainFrameListener(CatalogListWindow w) {
		return new BackToMainFrameListener();
	}

	// ProductListWindow
	public ActionListener getSelectProductListener(ProductListWindow w,
			boolean useDefData) {
		return new SelectProductListener(useDefData);
	}

	public ActionListener getBackToCatalogListListener(ProductListWindow w) {
		return new BackToCatalogListListener();
	}

	// ProductDetails Window

	public ActionListener getAddToCartListener(ProductDetailsWindow w) {
		return new AddEditCartItemListener(false);
	}

	public ActionListener getEditCartListener(CartItemsWindow w) {
		return new AddEditCartItemListener(true);
	}

	public ActionListener getDeleteCartListener(CartItemsWindow w) {
		return new DeleteCartItemListener();
	}

	public ActionListener getBackToProductListListener(ProductDetailsWindow w) {
		return new BackToProductListListener();
	}

	// CartItemsWindow

	public ActionListener getContinueShoppingListener(CartItemsWindow w) {
		return (new ContinueShoppingListener());
	}

	public ActionListener getSaveCartListener(CartItemsWindow w) {
		return (new SaveCartListener());
	}

	public ActionListener getQuantityOkListener(QuantityWindow w, boolean edit,
			Integer posOfEdit) {
		return new QuantityOkListener(edit, posOfEdit);
	}
	
	public ActionListener getRetrieveCartActionListener(EbazaarMainFrame f) {
		return (new RetrieveCartActionListener());
	}

	// ////// public setters to register screens controlled by this class////

	public void setCatalogList(CatalogListWindow w) {
		catalogListWindow = w;
	}

	public void setMainFrame(EbazaarMainFrame m) {
		mainFrame = m;
	}

	public void setProductListWindow(ProductListWindow p) {
		productListWindow = p;
	}

	public void setProductDetailsWindow(ProductDetailsWindow p) {
		productDetailsWindow = p;
	}

	public void setCartItemsWindow(CartItemsWindow w) {
		cartItemsWindow = w;
	}

	public void setSelectOrderWindow(SelectOrderWindow w) {
	}

	public void setMaintainCatalogTypes(MaintainCatalogTypes w) {
	}

	public void setMaintainProductCatalog(MaintainProductCatalog w) {
	}

	public void setQuantityWindow(QuantityWindow w) {
		quantityWindow = w;
	}

	private EbazaarMainFrame mainFrame;
	private ProductListWindow productListWindow;
	private CatalogListWindow catalogListWindow;
	private ProductDetailsWindow productDetailsWindow;
	private CartItemsWindow cartItemsWindow;
	private QuantityWindow quantityWindow;

}
